using Innovation;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;

namespace TestEnvironment
{
    public class Game1 : Game
    {
        // The IGraphicsDeviceService the engine will use
        GraphicsDeviceManager graphics;

        public Game1()
        {
            // Setup graphics
            graphics = new GraphicsDeviceManager(this);
        }

        protected override void LoadContent()
        {
            // Setup engine. We do this in the load method
            // so that we know graphics will be ready for use
            Engine.SetupEngine(graphics);

            // Create a new Camera
            FPSCamera camera = new FPSCamera();
            //Camera camera = new Camera();

            // Setup its position and target
            camera.Transform.Position = new Vector3(3, 3, 5);
            camera.RotateTranslate(new Vector3(-.5f, .55f, 0), Vector3.Zero);

            // Add it to the service container
            Engine.Services.AddService(typeof(Camera), camera);

            // Setup physics
            Engine.Services.AddService(typeof(Physics), new Physics());

            // Create the plane and make it immovable
            PhysicsActor plane = new PhysicsActor("Content\\ig_plane", 
                new BoxObject(new Vector3(4, .01f, 4)));
            plane.PhysicsObject.Immovable = true;
            plane.ModelValue.GenerateMaterials<LitMaterial>();

            // Create the plane object
            PlaneObject p = new PlaneObject();

            // Create the stack of boxes
            for (int y = 0; y < 3; y++)
                for (int x = 0; x < 3; x++)
                {
                    PhysicsActor act = new PhysicsActor("Content\\ig_box", new BoxObject(
                        new Vector3(.5f), 
                        new Vector3(- .5f + (x * 0.52f), .5f + (y * 0.52f), -1), 
                        Vector3.Zero));

                    act.Transform.Scale = new Vector3(.5f);
                    act.ModelValue.GenerateMaterials<LitMaterial>();
                }

            MouseDevice mouse = new MouseDevice();
            KeyboardDevice keyboard = new KeyboardDevice();
            Engine.Services.AddService(typeof(MouseDevice), mouse);
            Engine.Services.AddService(typeof(KeyboardDevice), keyboard);
        }

        protected override void Update(GameTime gameTime)
        {
            // Update the engine and game
            Engine.Update(gameTime);
            
            MouseDevice mouse = Engine.Services.GetService<MouseDevice>();
            KeyboardDevice keyboard = Engine.Services.GetService<KeyboardDevice>();

            FPSCamera cam = (FPSCamera)Engine.Services.GetService<Camera>();

            if (mouse.WasButtonPressed(MouseButtons.Left))
            {
                Vector3 dir = cam.Target - cam.Transform.Position;

                PhysicsActor act = new PhysicsActor(
                    "Content\\ig_box",
                    new BoxObject(new Vector3(.5f), cam.Transform.Position + dir * .02f, Vector3.Zero));

                act.Transform.Scale = new Vector3(.5f);
                act.PhysicsObject.Mass = 10;
                act.ModelValue.GenerateMaterials<LitMaterial>();

                dir.Normalize();
                act.PhysicsObject.Velocity = dir * 10;
            }

            Vector3 inputModifier = new Vector3(
                    (keyboard.IsKeyDown(Keys.A) ? -1 : 0) + (keyboard.IsKeyDown(Keys.D) ? 1 : 0),
                    (keyboard.IsKeyDown(Keys.E) ? -1 : 0) + (keyboard.IsKeyDown(Keys.Q) ? 1 : 0),
                    (keyboard.IsKeyDown(Keys.W) ? -1 : 0) + (keyboard.IsKeyDown(Keys.S) ? 1 : 0)
                );

            cam.RotateTranslate(new Vector3(mouse.Delta.Y * -.002f, mouse.Delta.X * -.002f, 0), inputModifier * .08f);

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            // Draw the engine and game
            Engine.Draw(gameTime, ComponentType.All);
            base.Draw(gameTime);
        }
    }
}
